package com.czg.jsonschema2lombokpojo.rules;

import com.czg.jsonschema2lombokpojo.annotator.Annotator;
import com.czg.jsonschema2lombokpojo.config.DefaultGenerationConfig;
import com.czg.jsonschema2lombokpojo.config.GenerationConfig;
import com.czg.jsonschema2lombokpojo.annotator.Jackson2Annotator;
import com.czg.jsonschema2lombokpojo.NoopRuleLogger;
import com.czg.jsonschema2lombokpojo.RuleLogger;
import com.czg.jsonschema2lombokpojo.SchemaStore;
import com.czg.jsonschema2lombokpojo.util.NameHelper;
import com.czg.jsonschema2lombokpojo.util.ReflectionHelper;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JClassContainer;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JDocComment;
import com.sun.codemodel.JDocCommentable;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JPackage;
import com.sun.codemodel.JType;

/**
 * 为代码生成规则提供工厂/创建方法。
 */
public class RuleFactory {

    private RuleLogger logger;
    private NameHelper nameHelper;
    private ReflectionHelper reflectionHelper;
    private GenerationConfig generationConfig;
    private Annotator annotator;
    private SchemaStore schemaStore;

    /**
     * 使用给定的生成配置选项创建一个新的规则工厂。
     *
     * @param generationConfig
     *            类型生成的生成配置选项。这些配置选项将影响由该工厂创建的规则生成的java代码。
     * @param annotator
     *            注解器用于用构建JSON兼容类型所需的任何注解标记Java类型
     * @param schemaStore
     *            此工厂用于获取和存储schema的对象
     */
    public RuleFactory(GenerationConfig generationConfig, Annotator annotator, SchemaStore schemaStore) {
        this.generationConfig = generationConfig;
        this.annotator = annotator;
        this.schemaStore = schemaStore;
        this.nameHelper = new NameHelper(generationConfig);
        this.reflectionHelper = new ReflectionHelper(this);
        this.logger = new NoopRuleLogger();
    }

    /**
     * 使用默认的生成配置选项创建规则工厂。
     *
     * @see DefaultGenerationConfig
     */
    public RuleFactory() {
        this(new DefaultGenerationConfig(), new Jackson2Annotator(new DefaultGenerationConfig()), new SchemaStore());
    }

    /**
     * 提供一个规则实例，当在schema中找到“数组”声明时应应用该规则实例。
     *
     * @return 可以处理“array”声明的schema规则。
     */
    public Rule<JPackage, JClass> getArrayRule() {
        return new ArrayRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到“description”声明时应用该规则实例。
     *
     * @return 一个可以处理“description”声明的schema规则。
     */
    public Rule<JDocCommentable, JDocComment> getDescriptionRule() {
        return new DescriptionRule();
    }

    /**
     * 提供一个规则实例，当在schema中发现“$comment”声明时应用该规则实例。
     *
     * @return 一个可以处理“$comment”声明的schema规则。
     */
    public Rule<JDocCommentable, JDocComment> getCommentRule() {
        return new CommentRule();
    }

    /**
     * 提供一个规则实例，当在schema中找到“enum”声明时应用该规则实例。
     *
     * @return 返回一个可以处理“enum”声明的schema规则。
     */
    public Rule<JClassContainer, JType> getEnumRule() {
        return new EnumRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到“format”声明时应用该规则实例。
     *
     * @return 返回一个可以处理format声明的schema规则。
     */
    public Rule<JType, JType> getFormatRule() {
        return new FormatRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到“object”声明时应用该规则实例。
     *
     * @return 一个可以处理object声明的schema规则。
     */
    public Rule<JPackage, JType> getObjectRule() {
        return new ObjectRule(this, reflectionHelper);
    }

    /**
     * 提供一个规则实例，当在schema中找到“required”声明时应用该规则实例。
     *
     * @return 一个可以处理required声明的schema规则。
     */
    public Rule<JDefinedClass, JDefinedClass> getRequiredArrayRule() { return new RequiredArrayRule(this); }

    /**
     * 提供一个规则实例，当在schema中找到“properties”声明时应用该规则实例。
     *
     * @return 一个可以处理“properties”声明的schema规则。
     */
    public Rule<JDefinedClass, JDefinedClass> getPropertiesRule() {
        return new PropertiesRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到属性声明（“properties”声明的子声明）时应该应用该规则实例。
     *
     * @return 一个可以处理属性声明的schema规则。
     */
    public Rule<JDefinedClass, JDefinedClass> getPropertyRule() {
        return new PropertyRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到“required”声明时应用该规则实例。
     *
     * @return 一个可以处理required声明的schema规则。
     */
    public Rule<JDocCommentable, JDocCommentable> getRequiredRule() {
        return new RequiredRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找不到“required”声明时应用该规则实例。
     *
     * @return 一个可以处理required声明的schema规则。
     */
    public Rule<JDocCommentable, JDocCommentable> getNotRequiredRule() {
        return new NotRequiredRule(this);
    }

    /**
     * 提供一个规则实例，该实例应应用于节点以查找其等效Java类型。通常为必须为其找到/生成Java类型的属性、数组等调用。
     *
     * @return 一个schema规则，它可以为给定的schema节点找到/生成相关的Java类型。
     */
    public Rule<JClassContainer, JType> getTypeRule() {
        return new TypeRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中发现“additionalProperties”声明时应用该规则实例。
     *
     * @return 一个可以处理“additionalProperties”声明的schema规则。
     */
    public Rule<JDefinedClass, JDefinedClass> getAdditionalPropertiesRule() {
        return new AdditionalPropertiesRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到“title”声明时应用该规则实例。
     *
     * @return 可以处理“title”声明的schema规则。
     */
    public Rule<JDocCommentable, JDocComment> getTitleRule() {
        return new TitleRule();
    }

    /**
     * 提供一个规则实例，当在schema中找到schema声明时应用该规则实例。
     *
     * @return 一个可以处理schema声明的schema规则。
     */
    public Rule<JClassContainer, JType> getSchemaRule() {
        return new SchemaRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到属性声明时，应该应用该规则实例来为该属性分配任何适当的默认值。
     *
     * @return 一个可以处理“default”声明的schema规则。
     */
    public Rule<JFieldVar, JFieldVar> getDefaultRule() {
        return new DefaultRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到属性声明时应用该规则实例，为该属性分配任何最小/最大验证
     *
     * @return 一个可以处理“default”声明的schema规则。
     */
    public Rule<JFieldVar, JFieldVar> getMinimumMaximumRule() {
        return new MinimumMaximumRule(this);
    }

    /**
     * 提供了一个规则实例，当在schema中找到属性声明时，应该应用该规则实例，为该属性分配任何大小验证（minItems/maxItems）
     *
     * @return 一个可以处理“default”声明的schema规则。
     */
    public Rule<JFieldVar, JFieldVar> getMinItemsMaxItemsRule() {
        return new MinItemsMaxItemsRule(this);
    }

    /**
     * 提供了一个规则实例，当在schema中找到属性声明时，应该应用该规则实例，为该属性分配任何大小验证（minLength/maxLength）
     *
     * @return 一个可以处理“default”声明的schema规则。
     */
    public Rule<JFieldVar, JFieldVar> getMinLengthMaxLengthRule() {
        return new MinLengthMaxLengthRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到属性声明时应用该规则实例，为该属性分配数字验证。
     *
     * @return 一个可以处理“digits”声明的schema规则。
     */
    public Rule<JFieldVar, JFieldVar> getDigitsRule() {
        return new DigitsRule(this);
    }

    /**
     * 提供一个规则实例，当在schema中找到属性的“schema”声明时，应该应用该规则实例。
     *
     * @return 一个可以处理pattern声明的schema规则。
     */
    public Rule<JFieldVar, JFieldVar> getPatternRule() {
        return new PatternRule(this);
    }

    /**
     * 获取将影响由该工厂创建的规则生成的java代码的配置选项。
     *
     * @return 一个包含所有配置属性值的配置对象。
     */
    public GenerationConfig getGenerationConfig() {
        return generationConfig;
    }

    /**
     * 类型生成的生成配置选项。这些配置选项将影响由该工厂创建的规则生成的java代码。
     *
     * @param generationConfig
     *            生成配置
     */
    public void setGenerationConfig(final GenerationConfig generationConfig) {
        this.generationConfig = generationConfig;
        this.nameHelper = new NameHelper(generationConfig);
    }

    /**
     * 获取注解器，该注解器将根据所选注解样式将注解应用于生成的代码，以允许正确的序列化和反序列化。
     *
     * @return 一个注解器，可以为JSON支持注解各种代码结构
     */
    public Annotator getAnnotator() {
        return annotator;
    }

    /**
     * 注解器用于用构建JSON兼容类型所需的任何注解标记Java类型
     *
     * @param annotator
     *            注解器
     */
    public void setAnnotator(final Annotator annotator) {
        this.annotator = annotator;
    }

    /**
     * 提供一个规则日志记录器，抽象调用框架的日志方法
     *
     * @return 本机日志框架的日志记录器接口
     */
    public RuleLogger getLogger() {
        return logger;
    }

    /**
     * 工厂将提供给规则的记录器。
     *
     * @param logger
     *            日志记录器
     */
    public void setLogger(RuleLogger logger) {
        this.logger = logger;
    }

    /**
     * 获取查找并保存JSONschema的存储
     *
     * @return 在类型生成期间查找和缓存schema对象的存储区。
     */
    public SchemaStore getSchemaStore() {
        return schemaStore;
    }

    /**
     * 此工厂用于获取和存储schema的对象
     *
     * @param schemaStore
     *            schema存储
     */
    public void setSchemaStore(final SchemaStore schemaStore) {
        this.schemaStore = schemaStore;
    }

    /**
     * 获取用于生成规范化类名和字段名的名称帮助器。
     *
     * @return 一个名称助手实例，可用于规范化类名和字段名。
     */
    public NameHelper getNameHelper() {
        return nameHelper;
    }

    public ReflectionHelper getReflectionHelper()    {
        return reflectionHelper;
    }


    /**
     * 提供一个规则实例，当在schema中找到“媒体”声明时，应该应用该规则实例。
     *
     * @return 可以处理“media”声明的schema规则。
     */
    public Rule<JType, JType> getMediaRule() {
        return new MediaRule();
    }



    public Rule<JDocCommentable, JDocComment> getJavaNameRule() {
        return new JavaNameRule();
    }

}
